package com.songqi.common.core.utils;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.URLEncoder;
import java.util.*;

/**
 * @description: excel导出国际化工具类
 * @author: songqi(13776346982)
 * @date: 2022/10/10 14:31
 */
public class ExcelLangUtils {
    private static final int VALUE_SIZE = 3;

    public static void exportExcel(HttpServletResponse response, String fileName, Collection<?> list, Class<?> clazz, String language) throws NoSuchFieldException, IllegalAccessException {
        Map<String, Object> retMap = changeExcelAnnotationValue(clazz, language);
        Class changedClazz = (Class) retMap.get("clazz");
        Map<Field, String> fieldExcelAnnoNameValueMap = (Map<Field, String>) retMap.get("fieldExcelAnnoNameValuesMap");
        OutputStream out = null;
        Workbook workbook = null;
        try{
            ExportParams exportParams = new ExportParams();
            exportParams.setType(ExcelType.XSSF);
            workbook = ExcelExportUtil.exportExcel(exportParams, changedClazz, list);
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            out = response.getOutputStream();
            workbook.write(out);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            IOUtils.closeQuietly(out);
            resetExcelAnnotationValue(changedClazz, fieldExcelAnnoNameValueMap);
        }

    }

    private static Map<String, Object> changeExcelAnnotationValue(Class<?> pojoClass, String lang)
            throws NoSuchFieldException, IllegalAccessException {
        Map<String, Object> retMap = new HashMap<>();
        Map<Field, String> fieldExcelAnnoNameValuesMap = new HashMap<>();
        //获取实体类中所有字段
        Field[] fields = pojoClass.getDeclaredFields();

        for (Field field : fields) {
            // 获取字段上的注解
            Excel anoExcel = field.getAnnotation(Excel.class);
            if (anoExcel != null) {
                // 获取代理处理器
                InvocationHandler invocationHandler = Proxy.getInvocationHandler(anoExcel);
                // 获取私有 memberValues 属性
                Field f = invocationHandler.getClass().getDeclaredField("memberValues");
                f.setAccessible(true);
                // 获取实例的属性map
                Map<String, Object> memberValues = (Map<String, Object>) f.get(invocationHandler);
                // 获取属性值
                String excelValue = (String) memberValues.get("name");
                fieldExcelAnnoNameValuesMap.put(field, excelValue);
                if (StringUtils.isNotBlank(excelValue)) {
                    //根据传入的语言标识，重新设置属性值
                    List<String> valueList = Arrays.asList(excelValue.split(","));
                    if (valueList.size() == VALUE_SIZE) {
                        if (Locale.CHINESE.getLanguage().equals(lang)) {
                            memberValues.put("name", valueList.get(0));
                        }
                        if (Locale.ENGLISH.getLanguage().equals(lang)) {
                            memberValues.put("name", valueList.get(1));
                        }
                        if ("th".equals(lang)) {
                            memberValues.put("name", valueList.get(2));
                        }
                    }
                }
            }
        }
        retMap.put("clazz", pojoClass);
        retMap.put("fieldExcelAnnoNameValuesMap", fieldExcelAnnoNameValuesMap);
        return retMap;
    }


    private static void resetExcelAnnotationValue(Class<?> pojoClass, Map<Field, String> fieldExcelAnnoNameValuesMap) throws NoSuchFieldException, IllegalAccessException {
        Field[] fields = pojoClass.getDeclaredFields();
        for(Field field : fields){
            //获取字段上的注解
            Excel anoExcel = field.getAnnotation(Excel.class);
            if(anoExcel != null){
                String fieldExcelAnnoNameValue = fieldExcelAnnoNameValuesMap.get(field);
                //获取代理处理器
                InvocationHandler invocationHandler = Proxy.getInvocationHandler(anoExcel);
                // 获取私有memberValues属性
                Field f = invocationHandler.getClass().getDeclaredField("memberValues");
                f.setAccessible(true);
                //获取实例的属性map
                Map<String, Object> memberValues = (Map<String, Object>) f.get(invocationHandler);
                //获取属性值
                String excelValue = (String) memberValues.get("name");
                if(StringUtils.isNotBlank(excelValue)){
                    memberValues.put("name", fieldExcelAnnoNameValue);
                }
            }
        }

    }
}
